﻿//=============================================================================
// Project  : NIPO Component Framework
// File    : SimpleOutputPlugin.cs
// Author  : Bernhard Dieber (Bernhard.Dieber@uni-klu.ac.at)
// Copyright 2010 by Bernhard Dieber
// This code is published under the Microsoft Public License (Ms-PL).  A copy
// of the license should be distributed with the code.  It can also be found
// at the project website: http://NIPO.CodePlex.com.   This notice, the
// author's name, and all copyright notices must remain intact in all
// applications, documentation, and source files.
//=============================================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using NIPO.Data;
using NIPO.Plugins;
using NIPO.Util;

namespace NIPOPlugins.Output
{
    /// <summary>
    /// Writes byte data to file
    /// </summary>
    public class SimpleOutputPlugin:OutputPlugin
    {
        private SimpleOutputConfiguration _config = new SimpleOutputConfiguration();
        private FileStream _stream;

        #region Overrides of Plugin

        /// <summary>
        /// Opportunity for a plugin to do pre-start initialization (e.g. resource allocation, event registration, ...)<br/>
        ///             This method is called immediately before the framework start (after checking that IsConfigured == <c>true</c>
        /// </summary>
        /// <remarks>
        /// Registration of non-standard events is supposed to happen here. If your plugin is supposed to catch events other than normal data events, this should be done here.
        /// </remarks>
        protected override void Initialize()
        {
            _stream = File.Open(_config.TargetFile, FileMode.Create);
        }

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        public override void Dispose()
        {
            _stream.Flush();
            _stream.Close();
        }

        /// <summary>
        /// A plugin must provide a name
        /// </summary>
        /// <value>
        /// The name.
        /// </value>
        public override string Name
        {
            get { return "SimpleOutputPlugin"; }
        }

        /// <summary>
        /// Every plugin must provide a description on what it does
        /// </summary>
        /// <value>
        /// The description.
        /// </value>
        public override string Description
        {
            get { return "A simple output plugin to write binary data to a file"; }
        }

        /// <summary>
        /// The ConfigurationObject is used to have a user configure a plugin.<br/>
        ///             Provide here a subclass of PluginConfiguration that defines the configuration values of your need
        /// </summary>
        /// <value>
        /// The configuration object.
        /// </value>
        public override PluginConfiguration ConfigurationObject
        {
            get { return _config; }
            set { _config = (SimpleOutputConfiguration) value; }
        }

        /// <summary>
        /// Gets a value indicating whether this instance is configured.<br/>
        ///             "Configured" means that the plugin is ready to run and does not need any additional configuration information
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance is configured; otherwise, <c>false</c>.
        /// </value>
        public override bool IsConfigured
        {
            get { return !string.IsNullOrEmpty(_config.TargetFile); }
        }

        /// <summary>
        /// Resets a PlugIn after a framework run. After this call the plugin must be runnable again
        /// </summary>
        public override void Reset()
        {
            _stream.Flush();
            _stream.Close();
        }

        #endregion

        #region Overrides of OutputPlugin

        /// <summary>
        /// This method receives data from the preceeding processing plugin.
        /// </summary>
        /// <param name="sender">Reference to the sending plugin (instance of <see cref="T:NIPO.Plugins.ProcessingPlugin"/>)</param><param name="e">ArgumentsVector containing the data</param>
        public override void OutputData(object sender, NIPOEventArgs e)
        {
            if(e.Data is GenericDTO<byte[]>)
            {
                if(e.Data.ContentSize<=0) return;
                byte[] data = (e.Data as GenericDTO<byte[]>).Value;
                Log.WriteDebugFormat("Outputting {0} bytes of data", data.Length);

                _stream.Write(data, 0, data.Length);
                _stream.Flush();
            }
        }
        #endregion
        #region IInputChecker Members
        /// <summary>
        /// This method must return a set of acceptable inputs.
        /// </summary>
        /// <param eventName="possibleInput">A set of inputs that could be delivered by the preceeding plugin.</param>
        /// <returns>
        /// A set of acceptable inputs. This should be a subset of <paramref eventName="possibleInput"/>. The two sets will be checked for compatibility by the system.
        /// </returns>
        public ICollection<DataTransferObject> GetAcceptableInput(IEnumerable<DataTransferObject> possibleInput)
        {
            List<DataTransferObject> retVal = new List<DataTransferObject>();
            foreach (DataTransferObject dto in possibleInput)
            {
                if (dto is GenericDTO<byte[]>)
                    retVal.Add(dto);
            }
            return retVal;
        }

        /// <summary>
        /// Notifies the plugins what types of input it should expect.
        /// </summary>
        /// <remarks>
        /// This method may be called multiple times during the matching stage. 
        ///             The plugin should acceptall formats set in all calls.
        /// </remarks>
        /// <param eventName="input">The list of input types to expect from the preceeding plugins</param>
        /// <returns>
        /// <c>true</c> if the plugin will be able to accept all inputs, <c>false</c> otherwise
        /// </returns>
        public bool ExpectInput(DataTransferObject input, int id)
        {
            return input is GenericDTO<byte[]>;
        }

        #endregion
    }
}
